#!/usr/bin/php
<?php
declare(ticks = 1);

function cleanup($signal) {
	global $socket;
	socket_close($socket);
	exit;
}

$args = parseArgs($_SERVER['argv']);

$id=0;

pcntl_signal(SIGTERM, "cleanup");
pcntl_signal(SIGHUP,  "cleanup");
#pcntl_signal(SIGINT, "cleanup");

require("perfsonarnc.cfg.php");
require_once ("perfsonarnc.class.php");

$pnc=new perfsonarnc();

checkSocket();

if (($socket = socket_create(AF_UNIX, SOCK_STREAM, 0)) === false)
die("socket_create() failed: reason: " . socket_strerror(socket_last_error()));

if (socket_bind($socket, $cfg['socket']) === false) {
  print "socket_bind() failed: reason: " . socket_strerror(socket_last_error($socket))."\n";
  die("If no other instance of PerfsonarNCServer is running, try deleting the file ".$cfg['socket']."\n");
}
  
chmod($cfg['socket'],0777);

if (socket_listen($socket, SOMAXCONN) === false)
die("socket_listen() failed: reason: " . socket_strerror(socket_last_error($socket)));

pcntl_signal(SIGCHLD, SIG_IGN);
debug(1,"Ready");
do {	
	if (($msgsocket = socket_accept($socket)) === false)
		die("socket_accept() failed: reason: " . socket_strerror(socket_last_error($socket)));
	$pid = pcntl_fork();
	if ($pid == -1)
	die('could not fork');
	elseif($pid)
	$id++;
	else 
		connection($msgsocket,$pnc,$cfg);
} while (true);

socket_close($sock);

function checkSocket() {
	global $cfg;
	exec("netstat|grep ".$cfg['socket'],$out);
	if(count($out)>0)
		die("The socket ".$cfg['socket']." already exists and is in use\n");
	else if(file_exists($cfg['socket']))
		if(!unlink($cfg['socket']))
			die("Could not delete the socket file: ".$cfg['socket']."\n");
}

function debug($level,$msg) {
	global $args;
	if($args['debug']>=$level)
		print "$msg\n";
}

function connection($msgsocket,$pnc,$cfg) {
	debug(1,"New connection");
	$hello=false;
	//Send hello message
	socket_write($msgsocket,$pnc->hello()."\n]]>]]>\n");
	$xmlstr="";
	while(true) {
		if (socket_select($read=array($msgsocket), $write = NULL, $except = NULL, $cfg['timeout']) < 1)
	            exit();
	                if (false === ($str = socket_read($msgsocket, 2048, PHP_NORMAL_READ)))
	                        exit();
	                if(preg_match("/\]\]>\]\]/",$str)) {

		$dom=new domDocument();
			if(!$dom->loadXML($xmlstr))
			print "Could not load XML request: $xmlstr";
			else {
				$xp=new DOMXPath($dom);
				$xp->registerNamespace("nc","urn:ietf:params:xml:ns:netconf:base:1.0");
				$tmp=$xp->query("/nc:hello/nc:capabilities/nc:capability[.='urn:ietf:params:netconf:capability:xpath:1.0']");
				if (NULL != $tmp->item(0)) {
					$hello=true;
					debug(2,"Received hello message");
				} else {
					$tmp = $xp->query("/nc:rpc/@message-id");
					if (NULL == $tmp->item(0))
					print "Could not get message-id: $xmlstr\n";
					else {
						$id=$tmp->item(0)->textContent;
						debug(2,"New message");
						$tmp = $xp->query("/nc:rpc/nc:get/nc:filter[@type='xpath']/@select|/nc:rpc/nc:get-config/nc:filter[@type='xpath']/@select");
						if (NULL != $tmp->item(0)) {
							$xpath=$tmp->item(0)->textContent;
							$res=$pnc->get($id,$xpath);
							$str=$res->saveXML()."\n]]>]]>\n";
						} else {
							$tmp = $xp->query("/nc:rpc/nc:edit-config/nc:config/*");
							if (NULL != $tmp->item(0)) {
								$dom=new domdocument();
								$dom->appendChild($dom->importNode($tmp->item(0),true));
								$res=$pnc->editconfig($id,$dom);
								if($res)
								$str=$res->saveXML()."\n]]>]]>\n";
							} else {
								$tmp = $xp->query("/nc:rpc/nc:close-session");
								if (NULL != $tmp->item(0)) {
									$str="<?xml version='1.0'?><rpc-reply message-id='$id' xmlns='urn:ietf:params:xml:ns:netconf:base:1.0'><ok/></rpc-reply>\n]]>]]>\n";
					if(socket_write($msgsocket,$str)===false)
						die("socket_write() failed: reason: " . socket_strerror(socket_last_error($msgsocket)));
								exit();
								} else {
									print "Unsupported operation";
								}
							}
						}
					}
					if(socket_write($msgsocket,$str)===false)
						die("socket_write() failed: reason: " . socket_strerror(socket_last_error($msgsocket)));
					
				}
		
			}
			$xmlstr="";
		} else if(strlen($str)>1)
	                $xmlstr.=$str;
	}
}

function parseArgs($args) {

	$usage = "Usage: pncs.php <options>\n" .
    "Options:\n" .
	"\t-d run as daemon".
    "\t-v verbose\n";

	$ret = array ();
	$ret['debug']=0;

	for ($i = 1; $i < count($args); $i++) {
		switch ($args[$i]) {
			case '-v' :
				$ret['debug']++;
				break;			
			case '-d' :
				$pid = pcntl_fork();
				if ($pid == -1)
					die('could not fork to background');
				elseif($pid)
					exit();
				break;
			default :
				die("Illegal argument");
		}
	}

	return $ret;
}


?>